﻿#region Includes
using System;
using System.Runtime.InteropServices;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
#endregion

namespace GingerGL.Graphics
{
    //------------------------------------------------------------//
    /// <summary>
    /// Vertex Containing all needed information
    /// </summary>
    [Serializable]
    [StructLayout(LayoutKind.Sequential)]
    public struct Vertex
    {
        //--------------------------------------------------------//
        #region Variables
        /// <summary>
        /// X, Y, Z Coordinates
        /// </summary>
        public Vector3 Position;
        /// <summary>
        /// Vertex Normal 
        /// </summary>
        public Vector3 Normal;
        /// <summary>
        /// Texture Coords
        /// </summary>
        public Vector2 Texture;
        /// <summary>
        /// Light Map Texture Coordinates
        /// </summary>
        public Vector2 LightMap;
        /// <summary>
        /// Vertex Color
        /// </summary>
        public Color4 Color;
        /// <summary>
        /// Size of this Structure
        /// </summary>
        static public readonly int SizeInBytes = 
            (Vector3.SizeInBytes * 2) +     //Position, Normal
            (Vector2.SizeInBytes * 2) +     //Texture, Lightmap
            sizeof(float) * 4;              //Color
        #endregion
        //--------------------------------------------------------//
        #region Constructors
        /// <summary>
        /// Initializes a new instance of a Vertex
        /// </summary>
        /// <param name="pos">Position</param>
        /// <param name="norm">Normal</param>
        /// <param name="tex">Texture Coordinates</param>
        public Vertex(Vector3 pos, Color4 color)
        {
            Position = pos;
            Normal = pos;
            Normal.Normalize();
            Texture = Vector2.Zero;
            Color = color;
            LightMap = Vector2.Zero;
        }
        /// <summary>
        /// Initializes a new instance of a Vertex
        /// </summary>
        /// <param name="pos">Position</param>
        /// <param name="norm">Normal</param>
        /// <param name="tex">Texture Coordinates</param>
        public Vertex(Vector3 pos, Vector2 tex)
        {
            Position = pos;
            Normal = pos;
            Normal.Normalize();
            Texture = tex;
            Color = Color4.White;
            LightMap = Vector2.Zero;
        }
        /// <summary>
        /// Initializes a new instance of a Vertex
        /// </summary>
        /// <param name="pos">Position</param>
        /// <param name="norm">Normal</param>
        /// <param name="tex">Texture Coordinates</param>
        /// <param name="light">Lightmap Texture Coordinates</param>
        public Vertex(Vector3 pos, Vector2 tex, Vector2 light)
        {
            Position = pos;
            Normal = pos;
            Normal.Normalize();
            Texture = tex;
            Color = Color4.White;
            LightMap = light;
        }
        /// <summary>
        /// Initializes a new instance of a Vertex
        /// </summary>
        /// <param name="pos">Position</param>
        /// <param name="norm">Normal</param>
        /// <param name="tex">Texture Coordinates</param>
        /// <param name="light">Lightmap Texture Coordinates</param>
        public Vertex(Vector3 pos, Vector3 norm, Vector2 tex, Vector2 light)
        {
            Position = pos;
            Normal = norm;
            Texture = tex;
            Color = Color4.White;
            LightMap = light;
        }
        /// <summary>
        /// Initializes a new instance of a Vertex
        /// </summary>
        /// <param name="pos">Position</param>
        /// <param name="norm">Normal</param>
        /// <param name="tex">Texture Coordinates</param>
        public Vertex(Vector3 pos, Vector3 norm, Vector2 tex)
        {
            Position = pos;
            Normal = norm;
            Texture = tex;
            Color = Color4.White;
            LightMap = Vector2.Zero;
        }
        /// <summary>
        /// Initializes a new instance of a Vertex
        /// </summary>
        /// <param name="pos">Position</param>
        /// <param name="norm">Normal</param>
        /// <param name="tex">Texture Coordinates</param>
        /// <param name="color">Vertex Color</param>
        public Vertex(Vector3 pos, Vector3 norm, Vector2 tex, Color4 color)
        {
            Position = pos;
            Normal = norm;
            Texture = tex;
            Color = color;
            LightMap = Vector2.Zero;
        }
        #endregion
        //--------------------------------------------------------//
        #region Methods
        /// <summary>
        /// Sets Texture Variable
        /// </summary>
        public void SetLightMap(Vector2 lightmap)
        {
            LightMap = lightmap;
        }
        /// <summary>
        /// Sets Texture Variable
        /// </summary>
        public void SetTexture(Vector2 texcoord)
        {
            Texture = texcoord;
        }
        /// <summary>
        /// Sets Normal Variable
        /// </summary>
        /// <param name="norm"></param>
        public void SetNormal(Vector3 norm)
        {
            Normal = norm;
        }
        /// <summary>
        /// Sets Position Variable
        /// </summary>
        public void SetPosition(Vector3 pos)
        {
            Position = pos;
        }
        /// <summary>
        /// Sets Color Variable
        /// </summary>
        public void SetColor(Color4 color)
        {
            Color = color;
        }
        /// <summary>
        /// Calculates the offset in buffer
        /// </summary>
        static public int Offset(VertexOffset offset)
        {
            switch (offset)
            {
                case VertexOffset.Position: return 0;
                case VertexOffset.Normal: return Vector3.SizeInBytes;
                case VertexOffset.Texture0: return Vector3.SizeInBytes * 2;
                case VertexOffset.Texture1: return (Vector3.SizeInBytes * 2) + Vector2.SizeInBytes;
                case VertexOffset.Color: return (Vector3.SizeInBytes * 2) + (Vector2.SizeInBytes * 2);
                default: return 0;
            }
        }
        #endregion
        //--------------------------------------------------------//
        #region Operators
        static public Vertex operator +(Vertex left, Vertex right)
        {
            return new Vertex(
                left.Position + right.Position,
                left.Normal + right.Normal,
                left.Texture + right.Texture,
                left.LightMap + right.LightMap);

        }
        static public Vertex operator *(Vertex left, float right)
        {
            return new Vertex(
                left.Position * right,
                left.Normal * right,
                left.Texture * right,
                left.LightMap * right);
        }
        #endregion
        //--------------------------------------------------------//
    }
    //------------------------------------------------------------//
}
